from constants import *
import os
import re


class Parser():
    def __init__(self, rfile) -> None:
        self.instruction = []
        self.rfile = open(rfile)
        self.rfile_size = os.path.getsize(self.rfile.name)

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):
        self.rfile.close()

    def hasMoreLines(self) -> bool:
        return self.rfile.tell() != self.rfile_size

    def advance(self) -> str:
        if self.hasMoreLines():
            line = self.rfile.readline().rstrip().lstrip()
            # comment line
            if re.match(r'//.*', line):
                return self.advance()
            # blank line
            elif re.match(r'^\s*$', line):
                return self.advance()

            if "//" in line:
                line = line[0:line.index("//")]
            self.instruction = line.split(' ')
            return "".join(self.instruction)
        else:
            return ""

    def command_type(self):
        if self.instruction[0] == 'push':
            return C_PUSH
        elif self.instruction[0] == 'pop':
            return C_POP
        elif self.instruction[0] == 'label':
            return C_LABEL
        elif self.instruction[0] == 'goto':
            return C_GOTO
        elif self.instruction[0] == 'if-goto':
            return C_IF
        elif self.instruction[0] == 'function':
            return C_FUNCTION
        elif self.instruction[0] == 'return':
            return C_RETURN
        elif self.instruction[0] == 'call':
            return C_CALL
        elif self.instruction[0] in ['add', 'sub', 'neg', 'eq', 'gt', 'lt', 'and', 'or', 'not']:
            return C_ARITHMETIC

    def arg1(self) -> str:
        if self.command_type() == C_ARITHMETIC:
            return self.instruction[0]
        else:
            return self.instruction[1]

    def arg2(self) -> str:
        if self.command_type() in [C_PUSH, C_POP, C_FUNCTION, C_CALL]:
            return self.instruction[2]
        else:
            return ""
